#ifndef __MQ_CONSUMER_HPP__
#define __MQ_CONSUMER_HPP__

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <unordered_map>
#include <memory>
#include <mutex>
#include <sstream>
#include <functional>
#include "../mq_comm/mq_msg.pb.h"
#include "../mq_comm/helper.hpp"

namespace mq
{
    /*
        消费者回调函数
        参数1:消费者ID
        参数2:消息属性信息
        参数3:消息内容
    */
    using ConsumerCallback = std::function<void(const std::string &, const BasicProperties *bp, const std::string &)>;
    /*描述消费者信息类*/
    struct Consumer
    {
        using ptr = std::shared_ptr<Consumer>;
        std::string tag;           // 消费者ID
        std::string qname;         // 消息者订阅的队列名称
        bool auto_ack;             // 是否自动确认标志
        ConsumerCallback callback; // 消息回调函数

        Consumer()
        {
            DLOG("new consumer: %p", this);
        }

        Consumer(const std::string &_tag, const std::string &_qname, bool _auto_ack, const ConsumerCallback &_callback)
            : tag(_tag), qname(_qname), auto_ack(_auto_ack), callback(_callback)
        {
            DLOG("new consumer: %p", this);
        }

        ~Consumer()
        {
            DLOG("del consumer: %p", this);
        }
    };

    /*以队列管理订阅了某个队列的所有消费者*/
    class QueueConsumer
    {
    public:
        using ptr = std::shared_ptr<QueueConsumer>;
        QueueConsumer(const std::string &qname) : _qname(qname), _rr_seq(0) {}

        /*新增消费者*/
        Consumer::ptr create(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallback &cb)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 1.判断是否重复
            for (auto &consumer : _consumers)
            {
                if (consumer->tag == ctag)
                    return Consumer::ptr();
            }
            // 2.无重复条件下新增
            Consumer::ptr consumer = std::make_shared<Consumer>(ctag, queue_name, ack_flag, cb);
            _consumers.push_back(consumer);
            return consumer;
        }

        /*根据消费者ID,将消费者从消费者队列中移除*/
        void remove(const std::string &consumer_id)
        {
            std::unique_lock<std::mutex>(_mutex);
            // 1.判断是否存在
            for (auto iter = _consumers.begin(); iter != _consumers.end(); iter++)
            {
                if ((*iter)->tag == consumer_id)
                {
                    _consumers.erase(iter);
                    return;
                }
            }
            return;
        }

        /*通过RR轮转的方式获取消费者*/
        Consumer::ptr choose()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            // 1.判断消息者队列是否为空
            if (_consumers.empty() == true)
                return Consumer::ptr();
            int index = _rr_seq % _consumers.size();
            _rr_seq++;
            return _consumers[index];
        }

        /*判断消费者队列是否为空*/
        bool empty()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            return _consumers.empty();
        }

        /*根据消费者ID判断消费者是否存在*/
        bool exists(const std::string &consumer_id)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            for (auto &consumer : _consumers)
            {
                if (consumer->tag == consumer_id)
                    return true;
            }
            return false;
        }

        /*清理消费者队列*/
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _rr_seq = 0;
            _consumers.clear();
        }

    private:
        std::string _qname;                    // 队列名称
        std::mutex _mutex;                     // 互斥锁
        uint64_t _rr_seq;                      // 轮转序号
        std::vector<Consumer::ptr> _consumers; // 消费者队列
    };

    class ConsumerManager
    {
    public:
        using ptr=std::shared_ptr<ConsumerManager>;
        ConsumerManager(){}

        /*根据队列名将消费者队列初始化出来*/
        void initQueueConsumer(const std::string &qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto iter = _qconsumers.find(qname);
            if (iter != _qconsumers.end())
                return;
            QueueConsumer::ptr qcp = std::make_shared<QueueConsumer>(qname);
            _qconsumers.insert(std::make_pair(qname, qcp));
            return;
        }

        /*根据队列名称删除指定消费者队列*/
        void destroyQueueConsumer(const std::string &qname)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto iter = _qconsumers.find(qname);
            if (iter == _qconsumers.end())
                return;
            _qconsumers.erase(qname);
            return;
        }

        /*新增消费者添加进指定消费者队列中*/
        Consumer::ptr create(const std::string &ctag, const std::string &queue_name, bool ack_flag, const ConsumerCallback &cb)
        {
            QueueConsumer::ptr qcp = nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto iter = _qconsumers.find(queue_name);
                if (iter == _qconsumers.end())
                {
                    DLOG("没有找到队列%s的消费者管理句柄", queue_name.c_str());
                    return Consumer::ptr();
                }
                qcp = iter->second;
            }
            return qcp->create(ctag, queue_name, ack_flag, cb);
        }

        /*根据队列名称从指定的消费者队列中移除指定的消费者*/
        void remove(const std::string &consumer_id, const std::string &qname)
        {
            QueueConsumer::ptr qcp = nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto iter = _qconsumers.find(qname);
                if (iter == _qconsumers.end())
                {
                    DLOG("没有找到队列%s的消费者管理句柄", qname.c_str());
                    return;
                }
                qcp = iter->second;
            }
            return qcp->remove(consumer_id);
        }

        /*根据队列名称从指定的消费者队列中获取消费者句柄*/
        Consumer::ptr choose(const std::string &qname)
        {
            QueueConsumer::ptr qcp = nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto iter = _qconsumers.find(qname);
                if (iter == _qconsumers.end())
                {
                    DLOG("没有找到队列%s的消费者管理句柄", qname.c_str());
                    return Consumer::ptr();
                }
                qcp = iter->second;
            }
            return qcp->choose();
        }

        /*根据队列名称判断指定消费者队列是否为空*/
        bool empty(const std::string &qname)
        {
            QueueConsumer::ptr qcp = nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto iter = _qconsumers.find(qname);
                if (iter == _qconsumers.end())
                {
                    DLOG("没有找到队列%s的消费者管理句柄", qname.c_str());
                    return false;
                }
                qcp = iter->second;
            }
            return qcp->empty();
        }

        /*根据队列名称判断指定消费者队列中指定消费者是否存在*/
        bool exists(const std::string &consumer_id, const std::string &qname)
        {
            QueueConsumer::ptr qcp = nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto iter = _qconsumers.find(qname);
                if (iter == _qconsumers.end())
                {
                    DLOG("没有找到队列%s的消费者管理句柄", qname.c_str());
                    return false;
                }
                qcp = iter->second;
            }
            return qcp->exists(consumer_id);
        }

        /*清理所有消费者队列信息*/
        void clear()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            for(auto& iter:_qconsumers)
            {
                iter.second->clear();
            }
        }

    private:
        std::mutex _mutex; // 互斥锁
        std::unordered_map<std::string, QueueConsumer::ptr> _qconsumers;
    };
}

#endif